package com.jhl.seckill.config;

//import cn.hutool.json.JSONObject;

import com.alibaba.fastjson.JSONObject;
import com.jhl.seckill.utils.JWTUtil;
import com.jhl.seckill.vo.RespBean;
import com.jhl.seckill.vo.RespBeanEnum;
import io.jsonwebtoken.Claims;
import io.jsonwebtoken.ExpiredJwtException;
import io.jsonwebtoken.SignatureException;
import io.jsonwebtoken.UnsupportedJwtException;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.gateway.filter.GatewayFilterChain;
import org.springframework.cloud.gateway.filter.GlobalFilter;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.Ordered;
import org.springframework.core.io.buffer.DataBuffer;
import org.springframework.http.HttpStatus;
import org.springframework.http.server.reactive.ServerHttpRequest;
import org.springframework.http.server.reactive.ServerHttpResponse;
import org.springframework.util.StringUtils;
import org.springframework.web.server.ServerWebExchange;
import reactor.core.publisher.Mono;

import java.nio.charset.StandardCharsets;


@Configuration
@Slf4j
public class GatewayConfiguration implements GlobalFilter, Ordered {

    @Value("${gate.ignore.startWith}")
    private String startWith;

    @Override
    public Mono<Void> filter(ServerWebExchange exchange, GatewayFilterChain chain) {
        ServerHttpRequest request = exchange.getRequest();
        ServerHttpResponse response = exchange.getResponse();
        String requestUri = request.getPath().pathWithinApplication().value();

//        放行指定的请求
        if (isStartWith(requestUri) || isPrefix(requestUri, startWith)) {
            log.info("放行请求-->" + requestUri);
            ServerHttpRequest build = request.mutate().build();
            return chain.filter(exchange.mutate().request(build).build());
        }

//        获取token
        String token = request.getHeaders().getFirst("token");


//        如果token为空
        if (StringUtils.isEmpty(token)) {
            JSONObject message = new JSONObject();
            message.put("code", HttpStatus.UNAUTHORIZED.value());
            message.put("message", "认证失败，没有token");
            byte[] bytes = message.toString().getBytes(StandardCharsets.UTF_8);
            DataBuffer buffer = response.bufferFactory().wrap(bytes);
            response.getHeaders().add("Content-Type", "text/json;charset=UTF-8");
            return response.writeWith(Mono.just(buffer));
        }

//        Token不为空，需要进行验证
        try {
            Claims claims = JWTUtil.parseJWT(token);
            String user = claims.getSubject();
            System.out.println("从token获取的user=" + user);
//            token验证通过，给request加user，后端可以获取
            ServerHttpRequest serverHttpRequest = request.mutate().header("user", user).build();
            exchange.mutate().request(serverHttpRequest).build();

        } catch (ExpiredJwtException e) {
            log.error("用户Token过期异常", e);
            RespBean message = new RespBean(RespBeanEnum.TOKEN_EXPIRED_ERROR.getCode(), RespBeanEnum.TOKEN_EXPIRED_ERROR.getMessage(), null);

            return getVoidMono(exchange, message);
        } catch (SignatureException e) {
            log.error("Token签名验证失败", e);
            RespBean message = new RespBean(RespBeanEnum.TOKEN_VERIFIED_ERROR.getCode(), RespBeanEnum.TOKEN_VERIFIED_ERROR.getMessage(), null);
            return getVoidMono(exchange, message);
        } catch (UnsupportedJwtException e) {
            log.error("Token格式异常", e);
            RespBean message = new RespBean(RespBeanEnum.TOKEN_UNSUPPORTED_ERROR.getCode(), RespBeanEnum.TOKEN_UNSUPPORTED_ERROR.getMessage(), null);
            return getVoidMono(exchange, message);
        } catch (Exception e) {
            log.error("Token异常", e);
            RespBean message = new RespBean(RespBeanEnum.TOKEN_GLOBAL_ERROR.getCode(), e.getMessage(), null);
            return getVoidMono(exchange, message);
        }

        log.info("全局filter处理完毕");
//      放行请求
        return chain.filter(exchange);
    }

    /**
     * 网关抛异常
     */

    private Mono<Void> getVoidMono(ServerWebExchange exchange, RespBean message) {
        ServerHttpResponse response = exchange.getResponse();
        JSONObject jsonObject = new JSONObject();
        jsonObject.put("code", message.getCode());
        jsonObject.put("message", message.getMessage());
        jsonObject.put("data", message.getObject());
        byte[] bytes = jsonObject.toString().getBytes(StandardCharsets.UTF_8);
        DataBuffer buffer = response.bufferFactory().wrap(bytes);
        response.getHeaders().add("Content-Type", "text/json;charset=UTF-8");
        return response.writeWith(Mono.just(buffer));
    }


    private boolean isStartWith(String requestUri) {
        boolean flag = false;
        for (String s : startWith.split(",")) {
            if (requestUri.startsWith(s)) {
                return true;
            }
        }
        return flag;
    }

    private boolean isPrefix(String src, String target) {
        StringBuilder builder = new StringBuilder();
        int count = 0;
        for (String s : target.split(",")) {
            count = 0;
            for (int i = 0; i < s.length(); i++) {
                if (s.charAt(i) == '/') {
                    ++count;

                }
                builder.append(s.charAt(i));
                if (count == 2) {
                    break;
                }
            }
            builder = new StringBuilder();
            return src.contains(builder.toString());
        }
        return false;


    }


    @Override
//    用来指定filter的执行顺序，默认是按照自然数字进行排序
//    -1 在所有filter执行之前执行
    public int getOrder() {
        return 0;
    }


}
